package com.gosophia.commons.persistence;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;

import com.gosophia.commons.OrderCondition;
import com.gosophia.commons.Page;
import com.gosophia.commons.PropertyFilter;
import com.gosophia.commons.exception.BusinessException;

/**
 * 功能：通用的数据访问接口 ，为了使用不同的数据库访问框架，故此处只出现通用的操作方式
 * 
 * @author zhangdongsheng
 * @since 2010-7-29 Copyright (c) 2010 Gosophia corporation All Rights Reserved
 */
public interface EntityRepository<T, PK extends Serializable> {

    /**
     * 设置实体名称
     * 
     * @param entityClass
     * @param entityClassSimpleName
     */
    public void setEntityClassInfo(Class<T> entityClass,
            String entityClassSimpleName);

    /**
     * 获取当前session
     * 
     * @see com.gosophia.commons.Repository#getSession()
     */
    public Session getSession();

    /**
     * 新增实体
     * 
     * @param entity
     *            新增 实体
     * */
    public void save(final T entity);
    
    /**
     * 新增
     * 
     * @param entity
     *            新增 实体            
     * @return 主键
     */
    public Serializable add(final T entity);

    /**
     * 更新实体
     * 
     * @param entity
     *            需要更新的实体
     * 
     * */
    public void update(final T entity);

    /**
     * 
     * 更新实体指定的几个属性
     * 
     * @param id
     *            主键
     * @param version
     *            版本号
     * @param updatedParams
     *            要更新属性的键值对
     */
    public void update(final PK id, Long version, Map<String, Object> updatedParams);

    /**
     * 删除对象.
     * 
     * @param entity
     *            对象必须是session中的对象或含id属性的transient对象.
     */
    public void delete(final T entity);

    /**
     * 按id删除对象.
     * 
     * @param id
     *            根据实体Id删除
     */
    public void delete(final PK id);

    /**
     * 删除实体
     * 
     * @param id
     *            实体Id
     * @param version
     *            实体版本号
     * */
    public void delete(final PK id, Long version);

    /**
     * 按id获取对象.
     * 
     * @param id
     *            实体id
     */
    public T get(final PK id);

    /**
     * 获取全部对象.
     */
    public List<T> getAll();

    /**
     * 获取全部对象,支持排序.
     * 
     * @param orderConditions
     *            属性的排序条件
     */
    public List<T> getAllByOrder(List<OrderCondition> orderConditons);

    /**
     * 按属性查找对象列表,匹配方式为相等.
     * 
     * @param propertyName
     *            属性名称
     * @param value
     *            属性值
     */
    public List<T> findByProperty(final String propertyName, final Object value);

    /**
     * 根据一组属性查找对象列表
     * 
     * @param properties
     *            属性名称、属性值映射map
     * @return
     */
    public List<T> findByProperties(Map<String, Object> properties);

    /**
     * 按属性查找唯一对象,匹配方式为相等.
     */
    public T findUniqueByProperty(final String propertyName, final Object value);

    /**
     * 按id列表获取对象.
     */
    public List<T> findByIds(List<PK> ids);

    /**
     * 分页获取对象
     * */
    public Page<T> findPage(Page<T> page, OrderCondition... orderConditions);
    public Page<T> findPage(Page<T> page, List<OrderCondition> orderConditions);

    /**
     * 按属性过滤条件列表分页查找对象.
     */
    public Page<T> findPageByProperties(final Page<T> page,
            final List<PropertyFilter> propertyFilters, OrderCondition... orderConditions);

    /**
     * 全字段模糊搜索，注意搜索范围不包含实体Id
     * @throws BusinessException 当没有指定模糊匹配列时，抛出异常
     * */
    @Deprecated 
    public Page<T> allFiledSearching(Page<T> page, String searchStr,String orderbyStr, String orderbyFlg);

    /**
     * 全字段模糊搜索，注意搜索范围不包含实体Id
     * @throws BusinessException 当没有指定模糊匹配列时，抛出异常
     * */
    public Page<T> allFiledSearching(Page<T> page, String searchStr, String dateFormat,
            OrderCondition... orderConditions);
    
    /**
     * 全字段模糊搜索，注意搜索范围不包含实体Id
     * @throws BusinessException 当没有指定模糊匹配列时，抛出异常
     * */
    public Page<T> allFiledSearching(Page<T> page, String searchStr,
            List<OrderCondition> orderConditions);
    
    /**
     * 全字段模糊搜索，注意搜索范围不包含实体Id
     * @throws BusinessException 当没有指定模糊匹配列时，抛出异常
     * */
    public Page<T> allFiledSearching(Page<T> page, String searchStr, String dateFormat,
            List<PropertyFilter> propertyFilters, List<OrderCondition> orderConditions);
    
    /**
     * 全字段模糊搜索，注意搜索范围不包含实体Id
     * @throws BusinessException 当没有指定模糊匹配列时，抛出异常
     * */
    public Page<T> allFiledSearching(Page<T> page, String searchStr, String dateFormat,
            List<OrderCondition> orderConditions);
    
    /**
     * 全字段模糊搜索，注意搜索范围不包含实体Id
     * @throws BusinessException 当没有指定模糊匹配列时，抛出异常
     * */
    public Page<T> allFiledSearching(Page<T> page, String searchStr,
            OrderCondition... orderConditions);
    
    /**
     * 返回根据属性过滤条件过滤、排序后的Page对象
     * 
     * @param page
     *            数据分页对象
     * @param propertyFilters
     *            属性过滤列表，包含属性名称，属性值，属性操作符
     * @param orderConditions
     *            排序条件
     *            ，包含排序依据属性的名称，排序顺序（升序，或降序），例如按照"name"升序排序:OrderCondition.asc
     *            ("name")
     * */
    public Page<T> findPageByProperties(Page<T> page,
            List<PropertyFilter> propertyFilters,
            List<OrderCondition> orderConditions);

    /**
     * 刷新用
     */
    public void flush();

    /**
     * 根据 namedQuery的名称 进行查询
     * 
     * @param queryName
     *            命名查询
     * @param values
     *            命名查询的参数值 ，参数可以为0或多个
     * 
     * 
     * @see com.gosophia.commons.Repository#find(java.lang.String,
     *      java.util.Map)
     */
    <X> List<X> findListByNamedQuery(final String queryName,
            final Object... values);

    /**
     * 根据namedQuery 进行查询
     * 
     * @param queryName
     *            已定义的namedQuery名称
     * @param value
     *            命名查询的参数 Map集合
     * @see com.gosophia.commons.Repository#find(java.lang.String,
     *      java.util.Map)
     */
    <X> List<X> findListByNamedQuery(final String queryName,
            final Map<String, Object> values);

    /**
     * 根据命名查询唯一的对象
     * 
     * @param queryName
     *            已定以命名查询的名称
     * @param values
     *            命名查询的参数
     * @see com.gosophia.commons.Repository#findUnique(java.lang.String,
     *      java.util.Map)
     */
    <X> X findUniqueByNamedQuery(final String queryName,
            final Map<String, Object> values);
    
    /**
     * 根据namedQuery 名称 查询唯一的实体
     * 
     * @param queryName
     *            命名查询的名称
     *@param values
     *            命名查询参数，参数可为0或多个
     * @see com.gosophia.commons.Repository#findUnique(java.lang.String,
     *      java.util.Map)
     */
    <X> X findUniqueByNamedQuery(final String queryName, final Object... values);

    /**
     * 使用命名查询的方式进行分页查询
     * 
     * @param page
     *            查询page，封装了分页参数设定
     * @param queryName
     *            已定以命名查询，hql的格式为 from ClassName where propertyName1 = ? and
     *            propertyName2 = ?
     * @param values
     *            可变参数，需要参照查询字符串中参数的位置
     * @return
     */
    Page<T> findPageByNamedQuery(final Page<T> page, final String queryName,
            final Object... values);
    
    /**
     * 使用命名查询的方式进行分页查询
     * 
     * @param page
     *            查询page，封装了分页参数设定
     * @param queryName
     *            已定以命名查询，hql的格式为 from ClassName where propertyName1 = ? and
     *            propertyName2 = ?
     * @param values
     *            可变参数，需要参照查询字符串中参数的位置
     * @return
     */
    Page<T> findPageByNamedQuery(final Page<T> page, final String queryName,List<OrderCondition> orderConditions,
            final Object... values);

    /**
     * 使用命名查询的方式进行分页查询
     * 
     * @param page
     *            分页查询对象 封装了分页参数设定
     * @param queryName
     *            已定义命名查询名称
     * @param values
     *            参数值
     * @param orderConditions
     *            排序条件
     * @return
     */
    Page<T> findPageByNamedQuery(final Page<T> page, final String queryName,
            final Map<String, Object> values,OrderCondition... orderConditions);
    
    /**
     * 使用命名查询的方式进行分页查询
     * 
     * @param page
     *            分页查询对象 封装了分页参数设定
     * @param queryName
     *            已定义命名查询名称
     * @param values
     *            参数值
     * @param orderConditions
     *            排序条件
     * @return
     */
    Page<T> findPageByNamedQuery(final Page<T> page, final String queryName,
            final Map<String, Object> values,List<OrderCondition> orderConditions);

    //王新兵 2010-12-01
    /**
     * 使用Hql进行分页查询
     * 
     * @param page
     *            分页查询对象 ，封装了分页查询参数
     * @param hql
     *            HQl查询字符串,hql格式为
     * @param values
     *            hql查询参数值，需要参照hql中的参数顺序
     * @return
     */
    public Page<T> findPageByHql(final Page<T> page, final String hql, final Object... values);
    //王新兵 2010-12-01
    /**
     * 使用Hql进行分页查询
     * 
     * @param page
     *            分页查询对象 ，封装了分页查询参数
     * @param hql
     *            HQl查询字符串,hql 格式为：from ClassName where propertyName1
     *            =:propertyName1 and propertyName2 =:propertyName2
     * @param values
     *            hql查询参数值
     * @return
     */
    public Page<T> findPageByHql(final Page<T> page, final String hql,
            final Map<String, Object> values);
    /**
     * 根据namedQuery形式查询记录数，形式为 name :value
     * 
     * @param queryName
     * @param values
     * @return
     */
    public long countNamedQueryResult(final String queryName,
            final Map<String, Object> values);

    /**
     * 根据namedQuery形式查询记录数，形式参照 property =?
     * 
     * @param queryName
     * @param values
     * @return
     */
    public long countNamedQueryResult(final String queryName,
            final Object... values);

    /**
     * 执行没有返回值的NamedQuery
     * 
     * @param queryName
     *            名称
     * @param values
     *            参数集合
     */
    void executeNamedQuery(final String queryName, final Object... values);

    /**
     * 执行没有返回值的NamedQuery
     * 
     * @param queryName
     *            名称
     * @param values
     *            参数集合
     */
    void executeNamedQuery(final String queryName, final Map<String, Object> values);
    
    /**
     * 使用hql查询唯一的数据项
     * 
     * @see com.gosophia.commons.Repository#findUnique(java.lang.String,
     *      java.lang.Object)
     */
    public <X> X findUniqueByHql(final String hql, final Object... values);
    /**
     *清除Session中指定实体
     * @param entity
     */
    public void clearEntityOnSession(T entity);
    /**
     *清除Session
     */
    public void clearSession();
    
    /** 根据属性,排序条件查询,返回列表    wangxinbing 11.03.03*/
    /**
     * 根据属性,排序条件查询,返回列表
     * @param propertyFilters
     * @param orderConditions
     * @return 
     */
    public List<T> findListByProperties(List<PropertyFilter> propertyFilters,
            OrderCondition... orderConditions);
    /**
     * 根据属性,排序条件查询,返回列表
     * @param propertyFilters
     * @param orderConditions
     * @return
     */
    public List<T> findListByProperties(List<PropertyFilter> propertyFilters,
            List<OrderCondition> orderConditions);
}